package com.sensePlusVR.db;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;

import com.sensePlusVR.application.VRApplication;
import com.sensePlusVR.utils.ACache;
import com.sensePlusVR.utils.Constant;
import com.sensePlusVR.utils.DownloadOneUrl;
import com.sensePlusVR.utils.MyLog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("unused")
public class ImageLibrary{

	private static final String TAG = ImageLibrary.class.getSimpleName();
	private static final int MAX_TASKs = 5;
	private static ImageLibrary instance;
    private static final int MAX_SIZE = 1000 * 1000 * 200; // 200 mb
    private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量
	private long cache_size = -1;

	private static ACache mACache;
	private static ImageCache bitmapCache;
	private static Object lock;
	private static Object lockCallback;
	private static List<Notify> pendingList;
	
	public class Notify{
		public Callback callback;
		public String filePath;
		public String imageUrl;
		public Bitmap bitmap;
		public Notify(Callback callback, String filePath, String imageUrl){
			this.callback = callback;
			this.filePath = filePath;
			this.imageUrl = imageUrl;
		}
	} 
		
	private ImageLibrary() {
	}

	public static String getImageCacheDir() {
		return VRApplication.getAppContext().getExternalCacheDir() + "/images";
	}
	// sdcard/Android/data/com.jwaoo.main/cache/images/xxx.png
	public static ImageLibrary getInstance() {
		if (instance == null) {
			File cacheDir = new File(getImageCacheDir());
			if (!cacheDir.exists())
				cacheDir.mkdirs();
			if (!cacheDir.exists()){
				MyLog.e(TAG, "ImageLibrary: cacheDir:"+getImageCacheDir() + "not exists");
			}
			mACache = ACache.get(new File(getImageCacheDir()), MAX_SIZE, MAX_COUNT);
			bitmapCache = ImageCache.getInstants();
			instance = new ImageLibrary();
			
			lock = new Object();
			lockCallback = new Object();
			pendingList = new ArrayList<Notify>();
		}
		return instance;
	}
	
	public void getImageBitmap(Context context, String imageUrl, Callback callback) {
		//MyLog.d(TAG, "getImageBitmap imageUrl..." + imageUrl);
		if(imageUrl == null)return;
		Bitmap b = getBitmapFromCache(imageUrl);
		if (b != null){
			callback.onImageDownloaded(b);
			return;
		}
		Notify n = getNotify(imageUrl, callback);
		if (n != null){
			BitmapLoadTask task = new BitmapLoadTask();
			task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, n);
		}
		//task.
	}
	
	private void involkeCallback(Notify n){
		List<Notify> delList = new ArrayList<Notify>();
		
		synchronized(lockCallback){
			for (Notify n1:pendingList){
				if (n.imageUrl.equals(n1.imageUrl)){
					MyLog.e(TAG, "callback:"+n1.imageUrl);
					//n1.bitmap = n.bitmap;
					n1.callback.onImageDownloaded(n.bitmap);
					delList.add(n1);
				}
			}
			for (Notify n1:delList){
				pendingList.remove(n1);
			}
		}
	}
	
	public class BitmapLoadTask extends AsyncTask<Notify, Void, Notify> {


		@Override
		protected void onPostExecute(Notify n) {
			MyLog.e(TAG, "call onPostExecute bitmap="+n.bitmap);
			involkeCallback(n);
		}

		@Override
		protected Notify doInBackground(Notify... params) {
			// TODO Auto-generated method stub
			MyLog.e(TAG, "do in background...");
			Notify n = params[0];
			Bitmap b = null;
			updateACache(n);
			if (n.bitmap != null){
				updateLRUCache(n);
				return n;
			}
			getBitmapFromNetwork(n);
			return n;
		}
	}

	private Bitmap updateLRUCache(Notify n){
		if (n.bitmap == null)
			return null;
		bitmapCache.put(n.imageUrl, n.bitmap);
		return n.bitmap;
	}
	
	private Bitmap updateACache(Notify n){
		mACache.putPicFile(n.imageUrl);
		n.bitmap = mACache.getBitmap(n.imageUrl);
		MyLog.e(TAG, "ACache  get bitmap="+n.bitmap);
		return  n.bitmap;
	}

	private Notify getNotify(String imageUrl,Callback callback)
	{
		String[] strs = imageUrl.split("/");
		final String fileName = strs[strs.length - 1];
		MyLog.d(TAG, "fileName : " + fileName);
		final String filePathDir = ImageHistory.getImageCacheDir();
		final String filePath = ImageHistory.getImageCacheDir() + "/"
				+ fileName;
		//MyLog.d(TAG, "filePath : " + filePath);
		Notify n = new Notify(callback, filePath, imageUrl);
		synchronized(lockCallback){
			for (Notify n1:pendingList){
				if (n1.imageUrl.equals(imageUrl)){
					pendingList.add(n);
					return null;
				}
			}
			pendingList.add(n);
		}
		return n;
	}
	private Bitmap getBitmapFromNetwork(Notify n){
		MyLog.d(TAG, "get bitmap from network");
		String imageUrl = n.imageUrl;
		String[] strs = imageUrl.split("/");
		final String fileName = strs[strs.length - 1];
		//MyLog.d(TAG, "fileName : " + fileName);
		if (Constant.SDCARD_EXIST) {
			final String filePathDir = getImageCacheDir();
			final String filePath = getImageCacheDir() + "/"
					+ fileName;
			MyLog.d(TAG, "filePath : " + filePath);

			DownloadOneUrl  download = new DownloadOneUrl(imageUrl, filePathDir);
			download.run();	
			MyLog.d(TAG, "get bitmap from network, ok. progress="+download.getProgressDirect());
			updateACache(n);
			return updateLRUCache(n);
		}
		return null;
	}

	private Bitmap getBitmapFromFile(Notify n)
	{
		Bitmap bitmap = null;
		MyLog.e(TAG, "get bitmap from ACache");
		bitmap = mACache.getBitmap(n.imageUrl);
		if (bitmap != null) {
			MyLog.d(TAG, "get bitmap from ACache, ok....");
			return bitmap;
		}
		return null;
	}
	
	private Bitmap getBitmapFromCache(String imageUrl){
		Bitmap bitmap = null;
		// 内存缓存中获取
		bitmap = bitmapCache.get(imageUrl);
		if (bitmap != null) {
			MyLog.d(TAG, "get bitmap from memory");
			//if (callback != null)
				//callback.onImageDownloaded(bitmap);
			return bitmap;
		}
		return null;
	}
	
	public static interface Callback {
		public void onImageDownloaded(Bitmap bitmap);
	}
	
	private boolean saveBitmapToFile(Bitmap bitmap, String filePath) {
		try {
			FileOutputStream fos = new FileOutputStream(filePath);
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
			fos.close();
			return true;
		} catch (Exception e) {
			MyLog.e(TAG, "saveBitmapToFile exception : " + e.getMessage());
			return false;
		}
	}

	private Bitmap getBitmapFromFile(String filePath) {
		//makeRootDirectory(filePath);
		Bitmap bitmap = null;
		try {
			if (filePath != null) {
				FileInputStream fis = new FileInputStream(filePath);
				bitmap = BitmapFactory.decodeStream(fis);
			}
		} catch (FileNotFoundException e) {
			MyLog.e(TAG, "getBitmapFromFile exception : " + e.getMessage());
			bitmap = null;
		}
		return bitmap;
	}

	public static void makeRootDirectory(String filePath) {
		File file = null;
		try {
			file = new File(filePath);
			if (!file.exists()) {
				file.mkdirs();
			}
		} catch (Exception e) {

		}
	}


}
